package club.kynb.mall.application.service;

import club.kynb.mall.application.constant.AuthConst;
import club.kynb.mall.application.constant.MallResultCode;
import club.kynb.mall.application.limiter.RateLimiter;
import club.kynb.mall.application.model.model.command.CaptchaSaveCommand;
import club.kynb.mall.application.model.model.command.SmsSendCommand;
import club.kynb.mall.application.model.model.dto.AppInfoDTO;
import club.kynb.mall.application.repository.AuthRepository;
import club.kynb.mall.basic.api.ISmsService;
import club.kynb.mall.basic.constant.SmsScene;
import club.kynb.mall.user.api.IUserService;
import club.kynb.mall.user.constant.UserType;
import club.kynb.mall.user.model.dto.UserDTO;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.pizza.common.web.exception.Errors;
import org.pizza.util.Checker;
import org.springframework.stereotype.Service;

import java.util.Optional;
import java.util.concurrent.TimeUnit;

/**
 * @author kynb_club@163.com
 * @since 2021/6/24 3:35 下午
 */
@Slf4j
@Service
@AllArgsConstructor
public class GlobalApplicationService {
    private final AuthRepository authRepository;
    private final RateLimiter rateLimiter;
    private final ISmsService iSmsService;
    private final IUserService iUserService;


    public void smsSend(SmsSendCommand command) {
        if (command.getScene().equals(SmsScene.REGISTRY.getScene())) {
            final Optional<UserDTO> optional = iUserService.getUserByPhone(command.getPhone(), UserType.CUSTOMER.code());
            Checker.ifThrow(optional.isPresent(), () -> Errors.BIZ.exception(MallResultCode.CODE_11008));
        }
        boolean exceedRate = rateLimiter.isExceedRate(getRateKey(command.getPhone()));
        Checker.ifThrow(exceedRate, () -> Errors.BIZ.exception(MallResultCode.CODE_11007));
        String code = iSmsService.smsSend(command.getPhone(), command.getScene());
        authRepository.saveVerificationCode(getSaveKey(command.getPhone()), code, AuthConst.SMS_EXPIRE);
        rateLimiter.limitRate(getRateKey(command.getPhone()), AuthConst.RATE, TimeUnit.SECONDS);
    }

    private String getRateKey(String key) {
        return String.format("%s:%s", AuthConst.AUTH_SMS_RATE, key);
    }

    private String getSaveKey(String key) {
        return String.format("%s:%s", AuthConst.SMS_CODE, key);
    }

    public void captchaSave(CaptchaSaveCommand captchaSaveCommand) {
        authRepository.saveVerificationCode(getCaptchaKey(captchaSaveCommand.getCaptchaKey()), captchaSaveCommand.getCaptchaCode(), AuthConst.CAPTCHA_EXPIRE);
    }

    private String getCaptchaKey(String key) {
        return String.format("%s:%s", AuthConst.CAPTCHA, key);
    }

    public AppInfoDTO getAppInfo() {
        final AppInfoDTO appInfoDTO = new AppInfoDTO();
        appInfoDTO.setVersion("v1.0");
        return appInfoDTO;
    }

}
